#include "player.hpp"

Player::Player(App* appPtr,Physic* physic) : m_app(appPtr), m_physic(physic)
{
    m_character = new Character(m_app);

    m_character->setType(CREATURE_CHARACTER);

    m_character->LoadScript("./script/CharacterLoader.script");

    m_character->CurrentAnimation()->SetGoBack(1);

    m_character->SetAnimation(CREATURE_IDLE);

    m_Space = 1;

    m_SpeedJump = 0;

    m_LastJumpClock = 0;

    m_LastWalkClock = 0;

    m_LastDecelerationWalkClock = 0;

    m_Direction = None;

    m_Deceleration = false;

    m_MouvementOfPlayer = INAIR;

    m_selectPlayer = DONKEY; // Is temporaire

    m_Decalage.x = 0;
    m_Decalage.y = 0;

    m_JumpClock.Reset();

    m_WaitingTime.Reset();
}

void Player::SetPosition(sf::Vector2f position)
{
    m_position = position;
    m_position.x = 90;

    m_character->CurrentAnimation()->SetPosition(position);
}

sf::Vector2f Player::GetPosition()
{
    return m_position;
}

void Player::AddLife(unsigned int life)
{
    m_life += life;
}

void Player::RemoveLife(unsigned int life)
{
    m_life -= life;
}

int Player::GetLife()
{
    return m_life;
}

void Player::AddBanane(unsigned int banana)
{
    m_banana += banana;
}

int Player::GetBanana()
{
    return m_banana;
}

void Player::AddKong(Kong letter)
{
    switch(letter)
    {
            case K:
            m_KONG[0] = 1;
        break;
            case O:
            m_KONG[1] = 1;
        break;
            case N:
            m_KONG[2] = 1;
        break;
            case G:
            m_KONG[3] = 1;
        break;
    }
}

bool Player::GetKong()
{
    for(int i = 0;i <= 3;i++)
    {
        if(!m_KONG[i])
            return false;
    }
    return true;
}


sf::Sprite Player::DrawCharacter()
{
    if(m_selectPlayer == DONKEY)
        return* m_character->CurrentAnimation();
}

void Player::Update(float ElapsedTime)
{
    if(m_MouvementOfPlayer == INAIR || m_MouvementOfPlayer == TAKEOFF)
    {
        Player::CharacterInAir();
        Player::Gravity();
    }

    //Move Donkey kong on the axis Y in relation with its size Y
    Animation();
    m_Decalage.y = m_character->CurrentAnimation()->GetSize().y;
    m_character->CurrentAnimation()->UpdateAnim(ElapsedTime);
    if(m_Decalage.y > 10 && m_character->CurrentAnimation()->GetSize().y != m_Decalage.y)
    {
        m_position.y -= m_character->CurrentAnimation()->GetSize().y - m_Decalage.y;
    }
    m_position.x -= m_Decalage.x;
    std::cout << m_position.x << " " << m_character->CurrentAnimation()->CurrentFrame() << std::endl;
    m_character->CurrentAnimation()->SetPosition(m_position);
    m_position.x += m_Decalage.x;
}

void Player::Input(const sf::Input& input)
{
    if(input.IsKeyDown(sf::Key::Space))
    {
        if(m_Space == 0)
        {
            if(m_MouvementOfPlayer != INAIR || m_MouvementOfPlayer != TAKEOFF)
            {
                m_JumpClock.Reset();
                m_SpeedJump = MaxSpeedJump;
            }
            m_MouvementOfPlayer = TAKEOFF;
            Player::Gravity();
        }
        else
        {
            if(m_JumpClock.GetElapsedTime() < MaxMaintainOfSpace && m_MouvementOfPlayer == TAKEOFF)
            {
                m_SpeedJump-= Accelerationjump;
            }
        }
    }
    if(input.IsKeyDown(sf::Key::Right) && (m_Direction == Right || m_Direction == None))
    {
        m_Direction = Right;
        m_Deceleration = false;
        if(m_WalkClock.GetElapsedTime() < 0.2)
        {
            m_position.x += ((Accelerationwalk + 200) * pow(m_WalkClock.GetElapsedTime(),2))/2 - ((Accelerationwalk + 200) * pow(m_LastWalkClock,2))/2;
            m_LastWalkClock = m_WalkClock.GetElapsedTime();
        }
        else
        {
            m_position.x += Accelerationwalk * m_WalkClock.GetElapsedTime() - Accelerationwalk * m_LastWalkClock;
            m_LastWalkClock = m_WalkClock.GetElapsedTime();
        }
    }
    else if(input.IsKeyDown(sf::Key::Left) && (m_Direction == Left || m_Direction == None))
    {
        m_Deceleration = false;
        m_Direction = Left;
        if(m_WalkClock.GetElapsedTime() < 0.2)
        {
            m_position.x -= ((Accelerationwalk + 200) * pow(m_WalkClock.GetElapsedTime(),2))/2 - ((Accelerationwalk + 200) * pow(m_LastWalkClock,2))/2;
            m_LastWalkClock = m_WalkClock.GetElapsedTime();
        }
        else
        {
            m_position.x -= Accelerationwalk * m_WalkClock.GetElapsedTime() - Accelerationwalk * m_LastWalkClock;
            m_LastWalkClock = m_WalkClock.GetElapsedTime();
        }
    }
    else if(!input.IsKeyDown(sf::Key::Right) && m_Direction == Right)
    {
        if(m_Deceleration == false)
            m_DecelerationClock.Reset();
        m_Deceleration = true;
        if(m_DecelerationClock.GetElapsedTime() < 0.1)
        {
            m_position.x += (DecelerateWalk * pow(0.2 - m_DecelerationClock.GetElapsedTime(),2))/2 - (DecelerateWalk * pow(0.2 - m_DecelerationClock.GetElapsedTime(),2))/2;
            m_LastDecelerationWalkClock = m_DecelerationClock.GetElapsedTime();
        }
        else
        {
            m_Deceleration = false;
            m_Direction = None;
            m_LastDecelerationWalkClock = 0;
        }
        m_WalkClock.Reset();
        m_LastWalkClock = 0;
    }
    else if(!input.IsKeyDown(sf::Key::Left) && m_Direction == Left)
    {
        if(m_Deceleration == false)
            m_DecelerationClock.Reset();
        m_Deceleration = true;
        if(m_DecelerationClock.GetElapsedTime() < 0.1)
        {
            m_position.x -= (DecelerateWalk * pow(0.2 - m_DecelerationClock.GetElapsedTime(),2))/2 - (DecelerateWalk * pow(0.2 - m_DecelerationClock.GetElapsedTime(),2))/2;
            m_LastDecelerationWalkClock = m_DecelerationClock.GetElapsedTime();
        }
        else
        {
            m_Deceleration = false;
            m_Direction = None;
            m_LastDecelerationWalkClock = 0;
        }
        m_WalkClock.Reset();
        m_LastWalkClock = 0;
    }
    else if(!input.IsKeyDown(sf::Key::Right) && !input.IsKeyDown(sf::Key::Left) && m_Deceleration == false)
    {
        m_MouvementOfPlayer = IDLE;
        m_Direction = None;
        m_WalkClock.Reset();
        m_LastWalkClock = 0;
    }
}

void Player::CharacterInAir()
{
    if(m_selectPlayer == DONKEY)
        m_Space = m_physic->in_air(m_position,m_character->CurrentAnimation()->GetSize().x,m_character->CurrentAnimation()->GetSize().y);
    /*else if(m_selectPlayer == DIDDY)
        //m_Space = m_physic->in_air(m_position,m_animation->GetHeight_DD(),m_animation->GetWidth_DD());*/
    if(m_Space == 0)
    {
        m_JumpClock.Reset();
        m_MouvementOfPlayer = IDLE;
    }
    else if(m_Space >= 0 && m_JumpClock.GetElapsedTime() < MaxMaintainOfSpace && m_MouvementOfPlayer != INAIR)
    {
        m_MouvementOfPlayer = TAKEOFF;
    }
    else if(m_JumpClock.GetElapsedTime() > MaxMaintainOfSpace)
    {
        m_MouvementOfPlayer = INAIR;
    }
}

void Player::Gravity()
{
    if(m_physic->Roof(m_position,m_character->CurrentAnimation()->GetSize().x,m_character->CurrentAnimation()->GetSize().y) > (((m_SpeedJump + Gravite*m_LastJumpClock)*m_LastJumpClock) - ((m_SpeedJump + Gravite*m_JumpClock.GetElapsedTime())*m_JumpClock.GetElapsedTime())))
    {
        if(m_MouvementOfPlayer == INAIR)
        {
                if((((m_SpeedJump + Gravite*m_JumpClock.GetElapsedTime())*m_JumpClock.GetElapsedTime()) - ((m_SpeedJump + Gravite*m_LastJumpClock)*m_LastJumpClock)) < m_Space)
                {
                    m_position.y += ((m_SpeedJump + Gravite*m_JumpClock.GetElapsedTime())*m_JumpClock.GetElapsedTime()) - ((m_SpeedJump + Gravite*m_LastJumpClock)*m_LastJumpClock);
                    m_LastJumpClock = m_JumpClock.GetElapsedTime();
                }
                else
                {
                    m_position.y += m_Space;
                    m_LastJumpClock = 0;
                }
        }
        else if(m_MouvementOfPlayer == TAKEOFF)
        {
            m_position.y += ((m_SpeedJump + Gravite*m_JumpClock.GetElapsedTime())*m_JumpClock.GetElapsedTime()) - ((m_SpeedJump + Gravite*m_LastJumpClock)*m_LastJumpClock);
            m_LastJumpClock = m_JumpClock.GetElapsedTime();
        }
    }
    else
    {
        m_position.y -= m_physic->Roof(m_position,m_character->CurrentAnimation()->GetSize().x,m_character->CurrentAnimation()->GetSize().y);
        m_SpeedJump = 0;
        m_LastJumpClock = 0;
        m_JumpClock.Reset();
    }
}

void Player::Animation()
{
    if(m_MouvementOfPlayer == IDLE)
    {
        if(m_WaitingTime.GetElapsedTime() >= 7 && m_character->CurrentAnimation()->CurrentFrame() == 1)// Animation Waiting
        {
            m_character->SetAnimation(CREATURE_WAITING);
            m_character->CurrentAnimation()->Play();
            if(m_character->CurrentAnimation()->CurrentFrame() == 1 && m_WaitingTime.GetElapsedTime() >= 9)
            {
                m_WaitingTime.Reset();
                m_character->CurrentAnimation()->Stop();
                m_character->CurrentAnimation()->SetFrame(0);
                m_character->SetAnimation(CREATURE_IDLE);
                m_character->CurrentAnimation()->SetFrame(0);
            }
        }
        if(m_WaitingTime.GetElapsedTime() >= 7)
        {
            switch(m_character->CurrentAnimation()->CurrentFrame())
            {
                case 5:
                m_Decalage.x = 1;
                break;
                case 6:
                m_Decalage.x = 0;
                break;
                case 7:
                m_Decalage.x = -1;
                break;
                case 8:
                m_Decalage.x = 0;
                break;
                case 9:
                m_Decalage.x = 1;
                break;
                case 10:
                m_Decalage.x = 1;
                break;
                case 11:
                m_Decalage.x = -1;
                break;
                case 12:
                m_Decalage.x = 8;
                break;
                case 13:
                m_Decalage.x = 8;
                break;
                case 14:
                m_Decalage.x = 7;
                break;
                case 15:
                m_Decalage.x = 7;
                break;
                case 16:
                m_Decalage.x = 6;
                break;
                case 17:
                m_Decalage.x = 7;
                break;
                case 18:
                m_Decalage.x = 7;
                break;
                case 19:
                m_Decalage.x = 5;
                break;
                case 20:
                m_Decalage.x = 5;
                break;
                case 21:
                m_Decalage.x = 7;
                break;
                case 22:
                m_Decalage.x = 6;
                break;
                case 23:
                m_Decalage.x = 7;
                break;
                case 24:
                m_Decalage.x = 4;
                break;
                case 25:
                m_Decalage.x = 5;
                break;
                case 26:
                m_Decalage.x = 7;
                break;
                case 27:
                m_Decalage.x = 7;
                break;
                case 28:
                m_Decalage.x = 5;
                break;
                case 29:
                m_Decalage.x = 7;
                break;
                case 30:
                m_Decalage.x = 6;
                break;
                case 31:
                m_Decalage.x = 7;
                break;
                case 32:
                m_Decalage.x = 5;
                break;
                case 33:
                m_Decalage.x = 5;
                break;
                case 34:
                m_Decalage.x = 6;
                break;
                case 35:
                m_Decalage.x = 5;
                break;
                case 36:
                m_Decalage.x = 4;
                break;
                case 37:
                m_Decalage.x = 5;
                break;
                case 38:
                m_Decalage.x = 6;
                break;
                case 39:
                m_Decalage.x = 8;
                break;
                case 40:
                m_Decalage.x = 10;
                break;
                case 41:
                m_Decalage.x = 9;
                break;
                case 42:
                m_Decalage.x = 1;
                break;
                case 43:
                m_Decalage.x = 1;
                break;
                case 44:
                m_Decalage.x = 1;
                break;
                case 45:
                m_Decalage.x = 0;
                break;
            }
        }
    }
    else
    {
        m_WaitingTime.Reset();
        m_Decalage.x = 0;
    }
}
